/**
 * 
 * Ashish Tomar
 * IDS Project - 2
 * Port Pairing and Statistics Generator
 * 
 */
#include <pcap.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h> 
#include <map>
#include <utility>
#include <sstream>
#include <string>
#include <fstream>
#include <vector>
#include <math.h>
using namespace std;



double current_time;
double start_time;
double diff_time;
int pkt_count;
long double buffer_total;
int currenthour;
int currenthour2;
ofstream out;

float sd_value;
double final_time;

double totaltimefile2;

/* tcpdump header (ether.h) defines ETHER_HDRLEN) */
#ifndef ETHER_HDRLEN 
#define ETHER_HDRLEN 14
#define SIZE_ETHERNET 14
#endif

typedef u_int tcp_seq;


struct sniff_tcp {
	u_short th_sport;	/* source port */
	u_short th_dport;	/* destination port */
	tcp_seq th_seq;		/* sequence number */
	tcp_seq th_ack;		/* acknowledgement number */
	u_char th_offx2;	/* data offset, rsvd */
#define TH_OFF(th)	(((th)->th_offx2 & 0xf0) >> 4)
	u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
	u_short th_win;		/* window */
	u_short th_sum;		/* checksum */
	u_short th_urp;		/* urgent pointer */
};



u_int16_t handle_ethernet
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
		packet);
u_char* handle_IP
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
		packet);

u_char* handle_IP_after_mean
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
		packet);

u_char* handle_IP_one
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*
		packet);



struct my_ip {
	u_int8_t	ip_vhl;		/* header length, version */
#define IP_V(ip)	(((ip)->ip_vhl & 0xf0) >> 4)
#define IP_HL(ip)	((ip)->ip_vhl & 0x0f)
	u_int8_t	ip_tos;		/* type of service */
	u_int16_t	ip_len;		/* total length */
	u_int16_t	ip_id;		/* identification */
	u_int16_t	ip_off;		/* fragment offset field */
#define	IP_DF 0x4000			/* dont fragment flag */
#define	IP_MF 0x2000			/* more fragments flag */
#define	IP_OFFMASK 0x1fff		/* mask for fragmenting bits */
	u_int8_t	ip_ttl;		/* time to live */
	u_int8_t	ip_p;		/* protocol */
	u_int16_t	ip_sum;		/* checksum */
	struct	in_addr ip_src,ip_dst;	/* source and dest address */
};



class ippair{
public:
	string src_ip;
	string dst_ip;

};





class portpair{
public: 
	long int src_port;
	long int dst_port;

	bool operator()(const class portpair s1,const  class portpair s2) const{
		if(s1.src_port != s2.src_port)
		{
			if(s1.src_port < s2.src_port)
			{
				return true;
			}
			else
				return false;
		}
		else{
			if(s1.dst_port < s2.dst_port)
			{
				return true;
			}
			else
				return false;
		}

	}
};


class classification{
public: class ippair ip;
class portpair ports;
bool pos;

bool operator()(const class classification s1,const  class classification s2) const{
	if(s1.ports.src_port != s2.ports.src_port)
	{
		if(s1.ports.src_port < s2.ports.src_port)
		{
			return true;
		}
		else
			return false;
	}
	else{

		return false;
	}

}

};

class stats{

public:
	long double volume;//(total pkts size/diff_time)
	double packet_rate;
	double avg_packet_size;//(total pkts size/count)
	int count;
	double stdevpacketsize;
	double stdevpacketrate;
	double interstdevpktrate;
	double interstdev;
	double inter_packet_rate;
	double pkt_rate_mean;
	map <int , int> hourlypacketcount;


	double time;
	double stdevpacketvol;
	double interstdevpktvol;
	double pkt_vol_mean;
	double inter_packet_vol;
	map <int , long double> hourlypacketsize;

};



class totalstats{
public:
	long int totalNoPackets ;
	double totalTimeSession;
	double totalpktrate;
	double totalAvgBytes ;
	long double totalVolume;

};

class totalstats testdata;
class totalstats traindata;




map <class portpair, class stats, class portpair> port_pairs;
map <class portpair, class stats, class portpair> secondport_pairs;
map <class portpair, class stats, class portpair> ::iterator itr;
map <class portpair, class stats, class portpair> ::iterator p;
map <int, int> ::iterator hrpo;
map <int, long double> ::iterator hrsize;
map <int, class classification>  pack;
map <int, class classification> ::iterator pk;

double calgauss(double mean,double sigma,double x){

	double twopi=2*(22/7);
	double val = 1/(sqrt(twopi*(sigma*sigma)));
	double expval =  (-(  ((x-mean)*(x-mean)) /(2*sigma*sigma) ));
	double final = val*(exp(expval));

	return final;

}


void addtomapsecond(class portpair tempp, class stats st_temp){
	// port_pairs.insert ( pair<class portpair, int >(tempp,100) );

	itr = secondport_pairs.find(tempp);

	final_time = st_temp.time;


	if (itr == secondport_pairs.end()){
		secondport_pairs.insert ( pair<class portpair, class stats >(tempp,st_temp) );
		//cout<<"yes"<<port_pairs[tempp];
	}

}



void iterateOverMap2(){

	for(p = secondport_pairs.begin(); p != secondport_pairs.end(); p++) {
		cout << p->first.src_port ;
		cout << "\t" << p->first.dst_port ;
		cout << "\t" << p->second.packet_rate ;
		cout << "\t" << p->second.avg_packet_size;
		cout << "\t" << p->second.volume;
		cout << "\t" << p->second.count ;
		cout << "\t" << p->second.time  ;
		cout << "\t" << p->second.stdevpacketsize ;
		cout << "\t" << p->second.pkt_rate_mean ;
		cout << "\t" << p->second.stdevpacketrate ;
		cout << "\t" << p->second.pkt_vol_mean ;
		cout << "\t" << p->second.stdevpacketvol<< endl ;
	}
	cout<<endl;

}





void checkforwholemapvol(int ch){

	static int xx=0;
	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		itr = secondport_pairs.find(p->first);
		if (itr == secondport_pairs.end()){

		}
		else{

			double mean=itr->second.pkt_vol_mean;
			double sigma=itr->second.stdevpacketvol;

			double x;


			hrsize = p->second.hourlypacketsize.find(ch);
			if (hrsize == p->second.hourlypacketsize.end()){
				x=0.0;

			}
			else{
				x = hrsize->second;
			}


			if(x == 0.0 || x <= 1){
				return;
			}

			double gauss=0;
			//use gauss formula here to get a value for var wgauss
			gauss=calgauss(mean,sigma,x);
			if(gauss<=sd_value){
				xx++;
				out<< xx <<". Gaussian Volume ANOMALY in "<<ch+1<<" hr with ports ";
				if(p->first.src_port!=-1)
					out<< p->first.src_port ;
				else
					out<<" ephemeral";
				out<<", ";

				if(p->first.dst_port!=-1)
					out<< p->first.dst_port ;
				else
					out<<" ephemeral";

				out<<" --  Packet volume is violating  the threshold - "<<sd_value<<", the actual value is "<<gauss<< " and the total packet bytes for this hour are "<<x<<endl;
			}


		}


	}
}


void addtopositive(int pkt_cc){

	pk=pack.find(pkt_cc);
	if (pk == pack.end()){
		cout<<"buggy";
	}
	else{
		pk->second.pos=true;
	}

}

void printpositive(){
	int countt=0,neg=0;
	for(pk = pack.begin(); pk != pack.end(); pk++) {


		if(	pk->second.pos==true){
			countt+=1;
		}
		else{
			neg++;
		}

	}

	cout<<"total pos "<<countt<<endl;

	cout<<"total neg "<<neg<<endl;;
}


void printpositivefull(){
	int countt=0,tot=0,realneg=0;
	for(pk = pack.begin(); pk != pack.end(); pk++) {


		if(	pk->second.pos==true ){
			tot++;

			//cout<<pk->second.ip.src_ip <<" : "<<pk->second.ports.src_port	<<", "<<pk->second.ip.dst_ip	<<" : "<<	pk->second.ports.dst_port<<endl;
		}
		else{
			realneg++;
		}


	}


}






void checkforwholemap(int ch){

	static int xx=0;
	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		itr = secondport_pairs.find(p->first);
		if (itr == secondport_pairs.end()){

		}
		else{

			double mean=itr->second.pkt_rate_mean;
			double sigma=itr->second.stdevpacketrate;

			double x;


			hrpo = p->second.hourlypacketcount.find(ch);
			if (hrpo == p->second.hourlypacketcount.end()){
				x=0.0;

			}
			else{
				x = hrpo->second;
			}


			if(x == 0.0 || x <= 1){
				return;
			}

			double gauss=0;
			//use gauss formula here to get a value for var wgauss
			gauss=calgauss(mean,sigma,x);
			if(gauss<=sd_value){
				xx++;
				out<<xx <<". Gaussian Rate ANOMALY in "<<ch+1<<" hr ";
				if(p->first.src_port!=-1)
					out<< p->first.src_port ;
				else
					out<<" ephemeral";
				out<<", ";

				if(p->first.dst_port!=-1)
					out<< p->first.dst_port ;
				else
					out<<" ephemeral";

				out<<" --  Packet rate is violating  the threshold - "<<sd_value<<", the actual value is "<<gauss<< " and the no of packet for this hour are "<<x<<endl;
			}


		}


	}
}



void justcheckdevonce(class portpair tempp,  double x, class ippair ipadd, int pk_count){

	static int xx=0;

	itr = secondport_pairs.find(tempp);
	if (itr == secondport_pairs.end()){

	}
	else{

		double mean=itr->second.avg_packet_size;
		double sigma=itr->second.stdevpacketsize;
		double gauss=0;

		if(x == 0.0){
			return;
		}

		gauss=calgauss(mean,sigma,x);
		//use gauss formula here to get a value for var wgauss
		if(gauss<=sd_value){
			addtopositive(pk_count);
			xx++;
			out<<xx <<". Gaussian PKT SIZE ANOMALY for "<<ipadd.src_ip<<" : ";

			if(tempp.src_port!=-1)
				out<< tempp.src_port ;
			else
				out<<" ephemeral";

			out<<", ";


			out<<ipadd.dst_ip<<" : ";

			if(tempp.dst_port!=-1)
				out<< tempp.dst_port ;
			else
				out<<" ephemeral";

			out<<" --  Packet size is violating the threshold - "<<sd_value<<", the actual value is "<<gauss<< " and the packet size is "<<x<<endl;
		}

	}
}


void checkeveryhour(){
	static int ch=currenthour;

	if(ch!=currenthour){
		checkforwholemap(ch);
		checkforwholemapvol(ch);
		ch=currenthour;
	}


}

void  lasthour(int ch){

	checkforwholemap(ch);
	checkforwholemapvol(ch);

}










void calculatetotalstats(){
	//train data
	double pk_total_count=0;
	long double total_buffer_pkts=0;

	for(p = secondport_pairs.begin(); p != secondport_pairs.end(); p++) {

		total_buffer_pkts+=(p->second.avg_packet_size * p->second.count);
		pk_total_count += p->second.count ;

	}

	traindata.totalNoPackets = pk_total_count ;
	traindata.totalTimeSession = (final_time/3600) ;
	traindata.totalpktrate = (double)(pk_total_count/final_time) ;
	traindata.totalAvgBytes = (double)(total_buffer_pkts/pk_total_count) ;
	traindata.totalVolume = (long double)(total_buffer_pkts/final_time) ;

}


void totalstats(){
	//test data
	testdata.totalNoPackets = pkt_count ;
	testdata.totalTimeSession =  (diff_time/3600) ;
	testdata.totalpktrate =  (double)(pkt_count/diff_time) ;
	testdata.totalAvgBytes = (double)(buffer_total/pkt_count);
	testdata.totalVolume = (long double)(buffer_total/diff_time);

}





void comparetotalstats(float threshold){
	out<<endl;
	out <<"--TOTAL TRAFFIC STATS  ---  START --"<<endl;
	double percbytes = ((testdata.totalAvgBytes-traindata.totalAvgBytes)/traindata.totalAvgBytes)*100;
	if (percbytes >= threshold){
		out<<"ANOMALY -- Total Avg Packet size is more than the threshold - "<<threshold<<", the actual value is "<<percbytes<<endl;
	}

	double percrate = ((testdata.totalpktrate-traindata.totalpktrate)/traindata.totalpktrate)*100;
	if (percrate >= threshold){
		out<<"ANOMALY -- Total Avg Packet rate is more than the threshold - "<<threshold<<", the actual value is "<<percrate<<endl;
	}

	double percvol = ((testdata.totalVolume-traindata.totalVolume)/traindata.totalVolume)*100;
	if (percvol >= threshold){
		out<<"ANOMALY -- Total Avg Packet volume is more than the threshold - "<<threshold<<", the actual value is "<<percvol<<endl;
	}
	out <<"--TOTAL TRAFFIC STATS  ---  END --"<<endl<<endl<<endl;
}



void compareportpairstats(float threshold){
	//compare port_pairs and secondport_pairs maps
	int l=0,m=0,tt=0;
	out<<"--PORT PAIRING TRAFFIC ALERTS --- START"<<endl;
	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {

		itr = secondport_pairs.find(p->first);
		if (itr == secondport_pairs.end()){

		}
		else{
			m++;
			double percbytes = ((p->second.avg_packet_size-itr->second.avg_packet_size)/itr->second.avg_packet_size)*100;
			if (percbytes >= threshold){

				out<<m<<". ANOMALY "<< p->first.src_port <<", "<<  p->first.dst_port<<" -- Total Avg Packet size is more than the threshold - "<<threshold<<", the actual value is "<<percbytes<<endl;
			}

			double percrate = ((p->second.packet_rate-itr->second.packet_rate)/itr->second.packet_rate)*100;
			if (percrate >= threshold){

				out<<m<<". ANOMALY "<< p->first.src_port <<", "<<  p->first.dst_port<<" -- Total Avg Packet rate is more than the threshold - "<<threshold<<", the actual value is "<<percrate<<endl;
			}

			double percvol = ((p->second.volume-itr->second.volume)/itr->second.volume)*100;
			if (percvol >= threshold){
				out<<m<<". ANOMALY "<< p->first.src_port <<", "<<  p->first.dst_port<<" -- Total Avg Packet volume is more than the threshold - "<<threshold<<", the actual value is "<<percvol<<endl;
			}


			if(percbytes >= threshold || percrate >= threshold || percvol >= threshold){
				tt++;
			}



			//Match found
			//compare the stats
		}

	}


	out<<"--PORT PAIRING TRAFFIC ALERTS --- END"<<endl<<endl<<endl;
}




void compareportpairstatsnew(float threshold){
	//compare port_pairs and secondport_pairs maps
	int l=0,m=0,tt=0;
	out<<"--NEW PORT PAIRING ALERTS --- START"<<endl;
	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {

		itr = secondport_pairs.find(p->first);



		if (itr == secondport_pairs.end()){

			l++;


			if(p->first.src_port==-1 || p->first.dst_port==-1){
				out<<l<<". New Type of connection betwen source port ";

			}
			else{
				out<<l<<". HIGH PRIORITY ------ New Type of connection between source port ";
			}

			if(p->first.src_port!=-1)
				out<<p->first.src_port;
			else
				out<<" ephemeral ";

			out<<" and destination port ";

			if(p->first.dst_port!=-1)
				out<<p->first.dst_port;
			else
				out<<" ephemeral ";
			out<<". This port pairing had total "<<p->second.count<<" packets." ;
			out<<endl;

			//if((l/secondport_pairs.size())){

			//}

		}
		else{
			//Match found
			//compare the stats
		}

	}


	out<<"--NEW PORT PAIRING ALERTS --- END"<<endl<<endl<<endl;
}








void compareportpaireachpacket(class portpair p, class ippair temp, int pkt_cc){
	//compare port_pairs and secondport_pairs maps
	static int l=0,m=0,tt=0;



	itr = secondport_pairs.find(p);



	if (itr == secondport_pairs.end()){

		l++;

		addtopositive(pkt_cc);

		if(p.src_port==-1 || p.dst_port==-1){
			out<<l<<". New Type of connection between  ";

		}
		else{
			out<<l<<". HIGH PRIORITY ------ New Type of connection between  ";
		}

		out <<"Source "<<temp.src_ip<<" : ";

		if(p.src_port!=-1)
			out<<p.src_port;
		else
			out<<" ephemeral ";

		out<<" and Destination ";

		out<<temp.dst_ip<<" : ";

		if(p.dst_port!=-1)
			out<<p.dst_port;
		else
			out<<" ephemeral.";


		out<<endl;

		//if((l/secondport_pairs.size())){

		//}

	}
	else{
		//Match found
		//compare the stats
	}





}















void comparemaps(float threshold, float threshold2){
	//AD code here
	//compare port_pairs and secondport_pairs maps
	//compare testdata and traindata total stats
	comparetotalstats(threshold);
	compareportpairstats(threshold2);
	compareportpairstatsnew(threshold2);

}



void addToMap(class portpair tempp, double pkybytes){
	// port_pairs.insert ( pair<class portpair, int >(tempp,100) );

	itr = port_pairs.find(tempp);
	class stats st_temp;
	buffer_total+=pkybytes;
	currenthour =(int)diff_time/3600;

	if (itr == port_pairs.end()){
		st_temp.count=1;
		st_temp.packet_rate=(double)(st_temp.count/diff_time);
		st_temp.avg_packet_size=pkybytes;
		st_temp.volume=(long double)((st_temp.avg_packet_size*st_temp.count)/diff_time);
		st_temp.interstdev=0;
		st_temp.interstdevpktrate=0;
		st_temp.interstdevpktvol=0;
		st_temp.inter_packet_rate=0;
		st_temp.inter_packet_vol=0;
		hrpo = st_temp.hourlypacketcount.find(currenthour);
		if (hrpo == st_temp.hourlypacketcount.end()){
			st_temp.hourlypacketcount.insert(pair<int , int>(currenthour,1) );

		}
		else{
			hrpo->second+=1;
		}

		hrsize = st_temp.hourlypacketsize.find(currenthour);
		if (hrsize == st_temp.hourlypacketsize.end()){
			st_temp.hourlypacketsize.insert(pair<int , long double>(currenthour,(long double)pkybytes) );

		}
		else{
			hrsize->second+=pkybytes;
		}


		//st_temp.cumulative_packet_size=pkybytes;
		port_pairs.insert ( pair<class portpair, class stats >(tempp,st_temp) );

		//cout<<"yes"<<port_pairs[tempp];

	}
	else{
		itr->second.count+=1;
		itr->second.packet_rate=(double)(itr->second.count/diff_time);
		//itr->second.cumulative_packet_size+=itr->second.cumulative_packet_size;
		itr->second.avg_packet_size=  (((itr->second.count-1)*itr->second.avg_packet_size) + pkybytes)/itr->second.count;
		itr->second.volume=(long double)((itr->second.avg_packet_size*itr->second.count)/diff_time);
		itr->second.interstdev =0;

		hrpo = itr->second.hourlypacketcount.find(currenthour);
		if (hrpo == itr->second.hourlypacketcount.end()){
			itr->second.hourlypacketcount.insert ( pair<int, int >(currenthour,1) );

		}
		else{
			hrpo->second+=1;
		}

		hrsize = itr->second.hourlypacketsize.find(currenthour);
		if (hrsize == itr->second.hourlypacketsize.end()){
			itr->second.hourlypacketsize.insert(pair<int , long double>(currenthour, (long double)pkybytes) );

		}
		else{
			hrsize->second+=pkybytes;
		}



	}
}


void checkonMap(class portpair tempp, double pkybytes, class ippair ipadd, int pkt_count){

	itr = port_pairs.find(tempp);


	currenthour=(int)(diff_time/3600);


	if (itr == port_pairs.end()){

	}
	else{
		justcheckdevonce(itr->first,pkybytes, ipadd,pkt_count);
		compareportpaireachpacket(tempp, ipadd, pkt_count);
		checkeveryhour();
	}
	//cout<<currenthour<<endl;





}



void readfiletwo(char * filename){

	string s;
	std::string line;
	ifstream inFile;
	inFile.open(filename);

	while (std::getline(inFile, line)){
		// cout << line;
		stringstream ss ;
		ss << line;
		vector<string> v;
		while (getline( ss, line, '\t' )) v.push_back( line );
		class portpair tempp;
		class stats stat_temp;
		// cout << "The tokens are:\n";
		for (int i = 0; i < v.size(); i++){
			// cout << i << ": " << v[ i ] << endl;
			if(i==0){

				tempp.src_port=atoi(v[i].c_str());
				// cout<<tempp.src_port;
			}
			if(i==1){

				tempp.dst_port=atoi(v[i].c_str());
				//   cout<<tempp.dst_port;
			}
			if(i==2){
				std::stringstream sss(v[i]);
				sss >> stat_temp.packet_rate;
				//stat_temp.packet_rate=atod(v[i].c_str());
				//  cout<<stat_temp.packet_rate;
			}
			if(i==3){
				std::stringstream sss(v[i]);
				sss >> stat_temp.avg_packet_size;

				//	cout<<endl<<stat_temp.avg_packet_size;
			}
			if(i==4){
				std::stringstream sss(v[i]);
				sss >> stat_temp.volume;

				//  	cout<<endl<<stat_temp.volume;

			}
			if(i==5){
				stat_temp.count=atoi(v[i].c_str());
				//cout <<endl <<stat_temp.count<<endl;

			}
			if(i==6){
				std::stringstream sss(v[i]);
				sss >> stat_temp.time;
				totaltimefile2=(int)((stat_temp.time/3600)+1);
			}

			if(i==7){
				std::stringstream sss(v[i]);
				sss >> stat_temp.stdevpacketsize;

			}

			if(i==8){
				std::stringstream sss(v[i]);
				sss >> stat_temp.pkt_rate_mean;



			}

			if(i==9){
				std::stringstream sss(v[i]);
				sss >> stat_temp.stdevpacketrate;

			}

			if(i==10){
				std::stringstream sss(v[i]);
				sss >> stat_temp.pkt_vol_mean;
			}


			if(i==11){
				std::stringstream sss(v[i]);
				sss >> stat_temp.stdevpacketvol;
			}

		}

		addtomapsecond(tempp, stat_temp);
	}
}




void updateToMap(class portpair tempp, double pkybytes){
	// port_pairs.insert ( pair<class portpair, int >(tempp,100) );

	itr = port_pairs.find(tempp);
	if (itr == port_pairs.end()){

		//cout<<"BUGGY "<<endl;

	}
	else{

		itr->second.interstdev +=(pkybytes-itr->second.avg_packet_size)     *		(pkybytes-itr->second.avg_packet_size);
		/*if(itr->second.count==1){
			cout<<itr->second.interstdev<<" "<<endl;

		}*/
	}
}



void updatestats(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {

		p->second.packet_rate =(double)(p->second.count/diff_time);
		p->second.volume=(long double)((p->second.avg_packet_size*p->second.count)/diff_time);

	}
}




void iterateOverMap(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		cout << p->first.src_port ;
		cout << "\t" << p->first.dst_port ;
		cout << "\t" << p->second.packet_rate ;
		cout << "\t" << p->second.avg_packet_size;
		cout << "\t" << p->second.volume;
		cout << "\t" << p->second.count ;
		cout << "\t" << diff_time << endl ;
	}
}


void iterateOverMapsd(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		cout << p->first.src_port ;
		cout << "\t" << p->first.dst_port ;
		cout << "\t" << p->second.packet_rate ;
		cout << "\t" << p->second.avg_packet_size;
		cout << "\t" << p->second.volume;
		cout << "\t" << p->second.count ;
		cout << "\t" << diff_time ;
		cout << "\t" << p->second.stdevpacketsize ;
		cout << "\t" << p->second.pkt_rate_mean ;
		cout << "\t" << p->second.stdevpacketrate ;
		cout << "\t" << p->second.pkt_vol_mean ;
		cout << "\t" << p->second.stdevpacketvol<< endl ;

		if(p->first.dst_port == 418){
			int t=1;
			for(int x=0;x<=currenthour;x++){
				hrpo = p->second.hourlypacketcount.find(x);


				hrsize = p->second.hourlypacketsize.find(x);

				cout<<hrpo->second<<"\t"<<hrsize->second<<endl;
				t++;
			}
			break;
		}


	}
}






void stdevforrate(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		for(int x=0;x<=currenthour;x++){
			hrpo = p->second.hourlypacketcount.find(x);
			if (hrpo == p->second.hourlypacketcount.end()){

			}
			else{


				p->second.interstdevpktrate +=(hrpo->second-p->second.pkt_rate_mean)     *		(hrpo->second-p->second.pkt_rate_mean);
			}

		}

		p->second.stdevpacketrate=sqrt(p->second.interstdevpktrate/(currenthour+1));

		/*if(p->second.count==1){
cout<<p->second.stdevpacketrate <<"  "<<  p->second.interstdevpktrate  <<endl;
			 }*/
	}


}





void stdevforvol(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		for(int x=0;x<=currenthour;x++){
			hrsize = p->second.hourlypacketsize.find(x);
			if (hrsize == p->second.hourlypacketsize.end()){

			}
			else{


				p->second.interstdevpktvol +=(hrsize->second - p->second.pkt_vol_mean)     *		(hrsize->second - p->second.pkt_vol_mean);
			}

		}


		p->second.stdevpacketvol=sqrt(p->second.interstdevpktvol/(currenthour+1));

		/*if(p->second.count==1){
cout<<p->second.stdevpacketrate <<"  "<<  p->second.interstdevpktrate  <<endl;
			 }*/
	}


}


void correctallmaps(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		for(int x=0;x<=currenthour;x++){
			hrpo = p->second.hourlypacketcount.find(x);
			if (hrpo == p->second.hourlypacketcount.end()){
				p->second.hourlypacketcount.insert ( pair<int, int >(x,0) );

			}

			hrsize = p->second.hourlypacketsize.find(x);
			if (hrsize == p->second.hourlypacketsize.end()){
				p->second.hourlypacketsize.insert ( pair<int, long double >(x,(long double)0.00) );

			}

		}


	}


	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		for(int x=0;x<=currenthour;x++){
			hrpo = p->second.hourlypacketcount.find(x);
			if (hrpo == p->second.hourlypacketcount.end()){

			}
			else{
				p->second.inter_packet_rate+=hrpo->second;

			}

			hrsize = p->second.hourlypacketsize.find(x);
			if (hrsize == p->second.hourlypacketsize.end()){

			}
			else{

				p->second.inter_packet_vol+=hrsize->second;
			}

		}

		p->second.pkt_rate_mean=p->second.inter_packet_rate/p->second.hourlypacketcount.size();
		p->second.pkt_vol_mean=p->second.inter_packet_vol/p->second.hourlypacketsize.size();

	}

}




/* just print a count every time we have a packet...                      
 * 
 *
 */
void my_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*	packet){

	static int count = 1;
	//fprintf(stdout,"%d, ",count);
	struct timeval tss=pkthdr->ts;

	if(count==1){
		start_time = (double)tss.tv_sec+(double)(tss.tv_usec/1000000);
	}
	current_time = (double)tss.tv_sec+(double)(tss.tv_usec/1000000);
	diff_time=current_time - start_time;
	if(diff_time==0.0){
		diff_time==0.0000001;
	}
	fflush(stdout);
	if(count%10==0){
		updatestats();
	}

	pkt_count=count;

	// u_int16_t type = handle_ethernet(args,pkthdr,packet);

	u_int16_t type = handle_ethernet(useless,pkthdr,packet);

	if(type == ETHERTYPE_IP)
	{/* handle IP packet */
		handle_IP(useless,pkthdr,packet);
	}
	count++;
}



void third_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*	packet){

	static int count = 1;
	//fprintf(stdout,"%d, ",count);
	struct timeval tss=pkthdr->ts;

	if(count==1){
		start_time = (double)tss.tv_sec+(double)(tss.tv_usec/1000000);
	}
	current_time = (double)tss.tv_sec+(double)(tss.tv_usec/1000000);
	diff_time=current_time - start_time;
	if(diff_time==0.0){
		diff_time==0.0000001;
	}
	fflush(stdout);


	pkt_count=count;

	// u_int16_t type = handle_ethernet(args,pkthdr,packet);

	u_int16_t type = handle_ethernet(useless,pkthdr,packet);

	if(type == ETHERTYPE_IP)
	{/* handle IP packet */
		handle_IP_one(useless,pkthdr,packet);
	}
	count++;
}



void stdev(){

	for(p = port_pairs.begin(); p != port_pairs.end(); p++) {
		p->second.stdevpacketsize = sqrt( p->second.interstdev /p->second.count);
		/*if(p->second.count==1){
				cout<<p->second.stdevpacketsize <<"  "<<  p->second.interstdev  <<endl;
	    }*/

	}

}



void second_callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*	packet){
	static int count = 1;
	//fprintf(stdout,"%d, ",count);
	// u_int16_t type = handle_ethernet(args,pkthdr,packet);

	u_int16_t type = handle_ethernet(useless,pkthdr,packet);

	if(type == ETHERTYPE_IP)
	{/* handle IP packet */
		handle_IP_after_mean(useless,pkthdr,packet);
	}

}



int main(int argc,char **argv){ 
	int i;
	char *dev; 
	char errbuf[PCAP_ERRBUF_SIZE];
	pcap_t* descr;
	const u_char *packet;
	struct pcap_pkthdr hdr;     /* pcap.h                    */
	struct ether_header *eptr;  /* net/ethernet.h            */
	struct bpf_program fp;      /* hold compiled program     */
	bpf_u_int32 maskp;          /* subnet mask               */
	bpf_u_int32 netp;           /* ip                        */
	buffer_total=0;

	if(argc != 8){ fprintf(stdout,"Usage: %s \"filter program\"\n"
			,argv[0]);return 0;}

	out.open(argv[7]);
	/* grab a device to peak into... */
	dev = pcap_lookupdev(errbuf);
	// if(dev == NULL)
	//{ fprintf(stderr,"%s\n",errbuf); exit(1); }
	sd_value=atof(argv[6]);
	/* ask pcap for the network address and mask of the device */
	pcap_lookupnet(dev,&netp,&maskp,errbuf);

	/* open device for reading this time lets set it in promiscuous
	 * mode so we can monitor traffic to another machine             */
	descr=pcap_open_offline(argv[2], errbuf);
	// descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
	if(descr == NULL)
	{ printf("pcap_open_live(): %s\n",errbuf); exit(1); }

	/* Lets try and compile the program.. non-optimized */
	if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
	{ fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }

	readfiletwo(argv[3]);


	/* set the compiled program as the filter */
	if(pcap_setfilter(descr,&fp) == -1)
	{ fprintf(stderr,"Error setting filter\n"); exit(1); }

	/* ... and loop */ 
	pcap_loop(descr,-1,my_callback,NULL);
	updatestats();
	//iterateOverMap();
	//totalstats();
	//cout<<" Doing It again ---" <<endl<<endl;

	descr=pcap_open_offline(argv[2], errbuf);
	// descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
	if(descr == NULL)
	{ printf("pcap_open_live(): %s\n",errbuf); exit(1); }

	/* Lets try and compile the program.. non-optimized */
	if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
	{ fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }

	/* set the compiled program as the filter */
	if(pcap_setfilter(descr,&fp) == -1)
	{ fprintf(stderr,"Error setting filter\n"); exit(1); }

	/* ... and loop */
	pcap_loop(descr,-1,second_callback,NULL);

	stdev();
	correctallmaps();
	stdevforrate();

	stdevforvol();

	//iterateOverMapsd();

	descr=pcap_open_offline(argv[2], errbuf);
	// descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf);
	if(descr == NULL)
	{ printf("pcap_open_live(): %s\n",errbuf); exit(1); }

	/* Lets try and compile the program.. non-optimized */
	if(pcap_compile(descr,&fp,argv[1],0,netp) == -1)
	{ fprintf(stderr,"Error calling pcap_compile\n"); exit(1); }

	/* set the compiled program as the filter */
	if(pcap_setfilter(descr,&fp) == -1)
	{ fprintf(stderr,"Error setting filter\n"); exit(1); }


	out<<endl<<"--REAL Time Gaussian alerts --START"<<endl;
	/* ... and loop */
	pcap_loop(descr,-1,third_callback,NULL);




	totalstats();

	calculatetotalstats();
	lasthour((int)diff_time/3600);

	out<<endl<<"--REAL Time Gaussian alerts --END"<<endl<<endl<<endl;


	out<<"--Alerts based on whole traffic--START"<<endl;
	comparemaps(atof(argv[4]),atof(argv[5]));

	out<<"--Alerts based on whole traffic --END"<<endl<<endl<<endl;
	cout <<"Total packets "<<pack.size()<<endl;
	printpositive();
	printpositivefull();
	return 0;


}



u_int16_t handle_ethernet(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char*	packet){
	u_int caplen = pkthdr->caplen;
	u_int length = pkthdr->len;
	struct ether_header *eptr;  /* net/ethernet.h */
	u_short ether_type;

	if (caplen < ETHER_HDRLEN)
	{
		//fprintf(stdout,"Packet length less than ethernet header length\n");
		return -1;
	}

	/* lets start with the ether header... */
	eptr = (struct ether_header *) packet;
	ether_type = ntohs(eptr->ether_type);

	/* Lets print SOURCE DEST TYPE LENGTH */
	//  fprintf(stdout,"ETH: ");
	//fprintf(stdout,"%s "
	//,ether_ntoa((struct ether_addr*)eptr->ether_shost));
	//fprintf(stdout,"%s "
	//,ether_ntoa((struct ether_addr*)eptr->ether_dhost));

	/* check to see if we have an ip packet */
	if (ether_type == ETHERTYPE_IP)
	{
		//  fprintf(stdout,"(IP)");
	}else  if (ether_type == ETHERTYPE_ARP)
	{
		//fprintf(stdout,"(ARP)");
	}else  if (eptr->ether_type == ETHERTYPE_REVARP)
	{
		//fprintf(stdout,"(RARP)");


	}else {
		//fprintf(stdout,"(?)");
	}
	//fprintf(stdout," %d\n",length);

	return ether_type;
}



u_char* handle_IP(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
	class portpair tempp;

	const struct sniff_tcp *tcp;
	u_int size_ip;
	const struct my_ip* ip;
	u_int length = pkthdr->len;
	u_int hlen,off,version;
	int i;
	int len;
	/* jump pass the ethernet header */
	ip = (struct my_ip*)(packet + sizeof(struct ether_header));
	size_ip = IP_HL(ip)*4;
	tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);

	tempp.src_port=ntohs(tcp->th_sport);
	tempp.dst_port=ntohs(tcp->th_dport);

	if( tempp.src_port>1024  ){
		tempp.src_port=-1;
	}

	if( tempp.dst_port>1024 ){
		tempp.dst_port=-1;
	}
	/*if(count==2){
		    			tempp.src_port=233;
		    			tempp.dst_port=66;
    }*/
	double pktbytes=pkthdr->len;
	addToMap(tempp,pktbytes);

	length -= sizeof(struct ether_header); 

	/* check to see we have a packet of valid length */
	if (length < sizeof(struct my_ip))
	{
		printf("truncated ip %d",length);
		return NULL;
	}

	len     = ntohs(ip->ip_len);
	hlen    = IP_HL(ip); /* header length */
	version = IP_V(ip);  /* ip version */

	/* check version */
	if(version != 4)
	{
		fprintf(stdout,"Unknown version %d\n",version);
		return NULL;
	}

	/* check header length */
	if(hlen < 5 )
	{
		fprintf(stdout,"bad-hlen %d \n",hlen);
	}

	/* see if we have as much packet as we should */
	if(length < len)
		printf("\ntruncated IP - %d bytes missing\n",len - length);

	/* Check to see if we have the first fragment */
	off = ntohs(ip->ip_off);
	if((off & 0x1fff) == 0 )/* aka no 1's in first 13 bits */
	{/* print SOURCE DESTINATION hlen version len offset */
		// fprintf(stdout,"IP: ");
		//fprintf(stdout,"%s ",	                inet_ntoa(ip->ip_src));
		//fprintf(stdout,"%s %d %d %d %d\n",		                inet_ntoa(ip->ip_dst), hlen,version,len,off);
	}

	return NULL;

}



u_char* handle_IP_after_mean(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
	class portpair tempp;

	const struct sniff_tcp *tcp;
	u_int size_ip;
	const struct my_ip* ip;
	u_int length = pkthdr->len;
	u_int hlen,off,version;
	int i;

	int len;

	/* jump pass the ethernet header */
	ip = (struct my_ip*)(packet + sizeof(struct ether_header));
	size_ip = IP_HL(ip)*4;
	tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);

	tempp.src_port=ntohs(tcp->th_sport);
	tempp.dst_port=ntohs(tcp->th_dport);

	if( tempp.src_port>1024  ){
		tempp.src_port=-1;
	}

	if( tempp.dst_port>1024 ){
		tempp.dst_port=-1;
	}
	/*if(count==2){
		    			tempp.src_port=233;
		    			tempp.dst_port=66;
	}*/
	double pktbytes=pkthdr->len;

	updateToMap(tempp,pktbytes);

	length -= sizeof(struct ether_header);

	/* check to see we have a packet of valid length */
	if (length < sizeof(struct my_ip))
	{
		printf("truncated ip %d",length);
		return NULL;
	}

	len     = ntohs(ip->ip_len);
	hlen    = IP_HL(ip); /* header length */
	version = IP_V(ip);  /* ip version */

	/* check version */
	if(version != 4)
	{
		fprintf(stdout,"Unknown version %d\n",version);
		return NULL;
	}

	/* check header length */
	if(hlen < 5 )
	{
		fprintf(stdout,"bad-hlen %d \n",hlen);
	}

	/* see if we have as much packet as we should */
	if(length < len)
		printf("\ntruncated IP - %d bytes missing\n",len - length);

	/* Check to see if we have the first fragment */
	off = ntohs(ip->ip_off);
	if((off & 0x1fff) == 0 )/* aka no 1's in first 13 bits */
	{/* print SOURCE DESTINATION hlen version len offset */
		// fprintf(stdout,"IP: ");
		//fprintf(stdout,"%s ",	                inet_ntoa(ip->ip_src));
		//fprintf(stdout,"%s %d %d %d %d\n",		                inet_ntoa(ip->ip_dst), hlen,version,len,off);
	}

	return NULL;

}




u_char* handle_IP_one(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* packet){
	class portpair tempp;
	class ippair tee;
	const struct sniff_tcp *tcp;
	u_int size_ip;
	const struct my_ip* ip;
	u_int length = pkthdr->len;
	u_int hlen,off,version;
	int i;
	int len;
	u_char *ptr;






	/* jump pass the ethernet header */
	ip = (struct my_ip*)(packet + sizeof(struct ether_header));
	size_ip = IP_HL(ip)*4;
	tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);

	tempp.src_port=ntohs(tcp->th_sport);
	tempp.dst_port=ntohs(tcp->th_dport);

	tee.src_ip= inet_ntoa(ip->ip_src);
	tee.dst_ip= inet_ntoa(ip->ip_dst);

	if( tempp.src_port>1024  ){
		tempp.src_port=-1;
	}

	if( tempp.dst_port>1024 ){
		tempp.dst_port=-1;
	}
	/*if(count==2){
		    			tempp.src_port=233;
		    			tempp.dst_port=66;
    }*/
	double pktbytes=pkthdr->len;


	classification c;
	c.ip=tee;
	c.ports=tempp;
	c.pos=false;
	pack.insert(pair<int, class classification >(pkt_count,c));

	checkonMap(tempp,pktbytes,tee,pkt_count);



	length -= sizeof(struct ether_header);

	/* check to see we have a packet of valid length */
	if (length < sizeof(struct my_ip))
	{
		printf("truncated ip %d",length);
		return NULL;
	}

	len     = ntohs(ip->ip_len);
	hlen    = IP_HL(ip); /* header length */
	version = IP_V(ip);  /* ip version */

	/* check version */
	if(version != 4)
	{
		fprintf(stdout,"Unknown version %d\n",version);
		return NULL;
	}

	/* check header length */
	if(hlen < 5 )
	{
		fprintf(stdout,"bad-hlen %d \n",hlen);
	}

	/* see if we have as much packet as we should */
	if(length < len)
		printf("\ntruncated IP - %d bytes missing\n",len - length);

	/* Check to see if we have the first fragment */
	off = ntohs(ip->ip_off);
	if((off & 0x1fff) == 0 )/* aka no 1's in first 13 bits */
	{
		/* print SOURCE DESTINATION hlen version len offset */
		// fprintf(stdout,"IP: ");
		//fprintf(stdout,"%s ",	                inet_ntoa(ip->ip_src));
		//fprintf(stdout,"%s %d %d %d %d\n",inet_ntoa(ip->ip_dst), hlen,version,len,off);
	}

	return NULL;

}

